//
//  SystemCDefinitions.h
//  SystemCTest2
//
//  Created by Christopher Kemsley on 1/27/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#ifndef _SystemCDefinitions
#define _SystemCDefinitions

#include <stdint.h>
#include "systemc.h"

#include "DelayedBinding.hpp"
#include "PubSub.hpp"



/* Helper Definitions */

#define	SymbolToString(symbol)		#symbol
#define	MethodId(class,method)		"-[" SymbolToString(class) "<" << this << "> " << SymbolToString(method) << "] -- "

#define	NamespaceBegin(name)		namespace name {
#define NamespaceEnd(name)			}




NamespaceBegin ( SystemC )

typedef ::int64_t	SInt64 ;
typedef ::uint64_t	UInt64 ;

typedef ::int32_t	SInt32 ;
typedef ::uint32_t	UInt32 ;

typedef ::int16_t	SInt16 ;
typedef ::uint16_t	UInt16 ;

typedef ::int8_t	SInt8 ;
typedef ::uint8_t	UInt8 ;

typedef union {
	UInt64	asUInt64 ;
	struct {
		UInt32	a ;
		UInt32	b ;
	} as2xUInt32 ;
	struct {
		UInt16	a ;
		UInt16	b ;
		UInt16	c ;
		UInt16	d ;
	} as4xUInt16 ;
	struct {
		UInt8	a ;
		UInt8	b ;
		UInt8	c ;
		UInt8	d ;
		UInt8	e ;
		UInt8	f ;
		UInt8	g ;
		UInt8	h ;
	} as8xUInt8 ;
} UInt64Breakout ;

NamespaceEnd ( SystemC )











/* Coordination */

#define		SCInterval			sc_time

#define		kSCIntervalFemtoSeconds	SC_FS
#define		kSCIntervalPicoSeconds	SC_PS
#define		kSCIntervalNanoSeconds	SC_NS
#define		kSCIntervalMicroSeconds	SC_US
#define		kSCIntervalMiliSeconds	SC_MS
#define		kSCIntervalSeconds		SC_SEC

#define		SCCurrentTime()		sc_time_stamp()





/* Basic Types */

#define		SCLogic			sc_logic
#define		SCLogicVector	sc_lv
#define		kSCLogicTrue	SC_LOGIC_1
#define		kSCLogicFalse	SC_LOGIC_0
#define		kSCLogic1		SC_LOGIC_1
#define		kSCLogic0		SC_LOGIC_0

#define		SCUIntN			sc_uint










/* Bindings */

template <typename IOType,typename SignalType>
class	SystemCBinding : public DelayedBinding
{
public:
	SystemCBinding	( IOType io , SignalType signal ) ;
	
protected:
	virtual void	bind () ;
	IOType		mIO ;
	SignalType	mSignal ;
} ;


template <typename IOType,typename SignalType>
void	bindIOToSignal			( IOType pIO , SignalType pSignal , bool forceImmediate = false ) ;

template <typename PortType,typename InterfaceType>
void	bindPortToInterface		( PortType pPort , InterfaceType pInterface , bool forceImmediate = false ) ;

/* PubSub enabled linking */
/* These will bind immediately if available */

template <typename InterfaceType>
void	bindPortToInterfaceNamed	( sc_port<InterfaceType> & inPort , std::string const & intName ) ;

template <typename SignalType>
void	bindInputToSignalNamed		( sc_in<SignalType> & inIOSignal , std::string const & sigName ) ;

template <typename SignalType>
void	bindOutputToSignalNamed		( sc_out<SignalType> & inIOSignal , std::string const & sigName ) ;





/* Easy classes */

/*
 Because of the use-case of this simulation engine, these classes are
 not designed with ability to safely change their publication names more
 than once. Doing so will yield undefined behavior.
 */

template <typename Type>
struct	SCOutputSignal
{
	SCOutputSignal () ;
	~SCOutputSignal () ;
	
	void	operator=	( std::string const & name ) ;
	void	operator<<	( Type const & value ) ;
	
private:
	sc_signal<Type>	mSignal ;
	sc_out<Type>	mOutput ;
	Publication<sc_signal<Type> >	mPublisher ;
} ;


template <typename Type>
struct	SCInputSignal
{
	SCInputSignal () ;
	~SCInputSignal () ;
	
	void			operator=	( std::string const & name ) ;
	void			operator>>	( Type & value ) ;
	Type const&		operator*	() ;
	sc_in<Type>*	operator->	() ;
	bool			isValid () ;
	
	sc_in<Type> const&	input () ;
	
private:
	sc_in<Type>	mInput ;
	Subscription<sc_signal<Type> >	mSignal ;
} ;



#include "SystemCDefinitions.hxx"
#endif
